package hk.com.ocsl.display
{
	import flash.display.DisplayObject;
	import flash.display.DisplayObjectContainer;
	
	import mx.automation.events.MarshalledAutomationEvent;
	
	public class Position
	{
		public static const ALIGN_TOP:String = "hk.com.ocsl.display.Position.ALIGN_TOP";
		public static const ALIGN_BOTTOM:String = "hk.com.ocsl.display.Position.ALIGN_BOTTOM";
		public static const ALIGN_MIDDLE:String = "hk.com.ocsl.display.Position.ALIGN_MIDDLE";
		public static const ALIGN_CENTER:String = "hk.com.ocsl.display.Position.ALIGN_CENTER";
		public static const ALIGN_LEFT:String = "hk.com.ocsl.display.Position.ALIGN_LEFT";
		public static const ALIGN_RIGHT:String = "hk.com.ocsl.display.Position.ALIGN_RIGHT";
		public static function absoluteCenter(foreground:DisplayObject, background:DisplayObject):DisplayObject
		{
				foreground.x = (background.width / 2) - (foreground.width / 2);
				foreground.y = (background.height / 2) + (foreground.height / 2);
				return foreground;
		}
		public static function right(target:DisplayObject,margin:int =0,parent:DisplayObjectContainer = null,previousSibling:DisplayObject = null):DisplayObject
		{
			parent = setParent(target,parent);
			previousSibling = setPreviousSibling(target,previousSibling);
			
			target.x = parent.width - target.width;
			if(previousSibling !== target)
				target.x -= (margin - previousSibling.width - previousSibling.x);
			return target;
		}
		public static function left(target:DisplayObject,margin:int =0,parent:DisplayObjectContainer = null,previousSibling:DisplayObject = null):DisplayObject
		{
			parent = setParent(target,parent);
			previousSibling = setPreviousSibling(target,previousSibling);
			target.x=0;
			if(previousSibling !== target)
				target.x += (margin + previousSibling.width + previousSibling.x);
			return target;
		}
		public static function center(parent:DisplayObjectContainer,margin:int =0):DisplayObjectContainer
		{
			var previousSibling:DisplayObject = null;
			var totWidth:Number = 0;
			
			var target:Vector.<DisplayObject> = new Vector.<DisplayObject>();
			for(var i:int = 0; i<parent.numChildren; i++)
			{
				target.push(parent.getChildAt(i));
				totWidth += parent.getChildAt(i).width;
			}
			for each(var c:DisplayObject in target)
			{
				c.x = (parent.width - totWidth) / 2;
				if(previousSibling !== null)
					c.x += previousSibling.x + previousSibling.width + margin;
				previousSibling = c;
			}				
			return parent;
		}
		
		public static function top(target:DisplayObject,margin:int =0,parent:DisplayObjectContainer = null,previousSibling:DisplayObject = null):DisplayObject
		{
			parent = setParent(target,parent);
			previousSibling = setPreviousSibling(target,previousSibling);
			target.y=0;
			if(previousSibling !== target)
				target.y += (margin + previousSibling.height + previousSibling.y);
			return target;
		}
		public static function bottom(target:DisplayObject,margin:int =0,parent:DisplayObjectContainer = null,previousSibling:DisplayObject = null):DisplayObject
		{
			parent = setParent(target,parent);
			previousSibling = setPreviousSibling(target,previousSibling);
			
			target.y = parent.height - target.height;
			if(previousSibling !== target)
				target.y -= (margin - previousSibling.height - previousSibling.y);
			return target;
		}
		public static function middle(parent:DisplayObjectContainer,margin:int =0):DisplayObjectContainer
		{
			var previousSibling:DisplayObject = null;
			var totHeight:Number = 0;
			
			var target:Vector.<DisplayObject> = new Vector.<DisplayObject>();
			for(var i:int = 0; i<parent.numChildren; i++)
			{
				target.push(parent.getChildAt(i));
				totHeight += parent.getChildAt(i).height;
			}
			for each(var c:DisplayObject in target)
			{
				c.y = (parent.height - totHeight) / 2;
				if(previousSibling !== null)
					c.y += previousSibling.y + previousSibling.height + margin;
				previousSibling = c;
			}				
			return parent;
		}
		
		protected static function setPreviousSibling(target:DisplayObject,previousSibling:DisplayObject=null):DisplayObject
		{
			if(!previousSibling)
			{
				if(target.parent.getChildIndex(target) === 0)
					return target;
				else
					return target.parent.getChildAt(target.parent.getChildIndex(target) -1);
			}
			return previousSibling;
		}
		
		protected static function setParent(target:DisplayObject,parent:DisplayObjectContainer=null):DisplayObjectContainer
		{
			if(!parent)
				return target.parent;
			else
				return parent;
		}
		/**
		 * @todo implement global to local
		 * 
		 **/
		public static function maximize(target:DisplayObject,parent:DisplayObjectContainer = null):void			
		{
			parent = setParent(target,parent);
			target.width = parent.width
			target.height = parent.height
			target.x = target.y = 0;
			
		}
		public static function align(parent:DisplayObjectContainer,hOrientation:String, vOrientation:String,hMargin:Number = 0,vMargin:Number = 0):DisplayObjectContainer
		{
			return vAlign(hAlign(parent,hOrientation,hMargin),vOrientation,vMargin);	
		}
		
		public static function vAlign(parent:DisplayObjectContainer,orientation:String,margin:Number=0):DisplayObjectContainer
		{
			var prevSibling:DisplayObject = null;
			for(var i:int = 0; i< parent.numChildren;i++)
			{
				var c:DisplayObject = parent.getChildAt(i);
				switch(orientation)
				{
					case ALIGN_LEFT :						
						left(c,margin,parent,prevSibling);	
					break;
					case ALIGN_CENTER :
						return center(parent,margin);						
					break;
					case ALIGN_RIGHT :
						right(c,margin,parent,prevSibling);
					break;
				}
				prevSibling = c;
			}
			return parent;
		}
		public static function hAlign(parent:DisplayObjectContainer,orientation:String,margin:Number=0):DisplayObjectContainer
		{
			var prevSibling:DisplayObject = null;
			for(var i:int = 0; i< parent.numChildren;i++)
			{
				var c:DisplayObject = parent.getChildAt(i);
				switch(orientation)
				{
					case ALIGN_TOP :						
						top(c,margin,parent,prevSibling);	
						break;
					case ALIGN_MIDDLE :
						return middle(parent,margin);						
						break;
					case ALIGN_BOTTOM :
						bottom(c,margin,parent,prevSibling);
						break;
				}
				prevSibling = c;
			}
			return parent;
		}
		
	}
}